home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / cp1.zip / EVAL1.C < prev    next >
C/C++ Source or Header  |  1993-06-10  |  5KB  |  157 lines

  1. ===========================================================================
  2.  BBS: The Abacus * HST/DS * Potterville, MI
  3. Date: 06-07-93 (03:21)             Number: 88
  4. From: BOB STOUT                    Refer#: 121
  5.   To: BYTES CRUNCHER                Recvd: NO  
  6. Subj: Parser                         Conf: (37) C++ Langua
  7. ---------------------------------------------------------------------------
  8. In a message of <Jun 05 00:29>, Bytes Cruncher (1:167/281@fidonet) writes:
  9.  
  10.  >I would like to know where I can find the code for a good parser to
  11.  >evaluate mathematical expression. If you can include the code in the
  12.  >message it would be greatly appreciated.
  13.  
  14.   From SNIPPETS:
  15.  
  16. /*
  17. **  EVAL.C - A simple mathematical expression evaluator in C
  18. **
  19. **  operators supported: (
  20. **                       )
  21. **                       +
  22. **                       -
  23. **                       *
  24. **                       /
  25. **                       ^
  26. **
  27. **  limitations: 1 - No precedence rules are implemented.
  28. **               2 - Numbers can be negated (e.g. "-13"), but not
  29. **                   expressions (e.g. "-(13)").
  30. **
  31. **  Original Copyright 1991 by Bob Stout as part of
  32. **  the MicroFirm Function Library (MFL)
  33. **
  34. **  This subset* version is hereby donated to the public domain.
  35. **
  36. **  *(The MFL version adds 150 lines of code, 5 level precedence,
  37. **    logarithmic and transcendental operators, pi as a constant,
  38. **    named variables, and fully understands negation.)
  39. */
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45. #include <math.h>
  46.  
  47. #define NUL '\0'
  48.  
  49. typedef enum {R_ERROR = -2 /* range */, ERROR /* syntax */, SUCCESS} STATUS;
  50.  
  51. static char   delims[]   = "+-*/^)(";           /* Tokens               */
  52. static char   op_stack[256];                    /* Operator stack       */
  53. static double arg_stack[256];                   /* Argument stack       */
  54. static char   token[256];                       /* Token buffer         */
  55. static int    op_sptr,                          /* op_stack pointer     */
  56.               arg_sptr,                         /* arg_stack pointer    */
  57.               parens,                           /* Nesting level        */
  58.               state = 0;                        /* 0 = Awaiting expression
  59.                                                    1 = Awaiting operator
  60.                                                 */
  61.  
  62. int evaluate(char *, double *);
  63.  
  64. static int        do_op(void);
  65. static int        do_paren(void);
  66. static void       push_op(char);
  67. static void       push_arg(double);
  68. static STATUS     pop_arg(double *);
  69. static STATUS     pop_op(int *);
  70. static char      *getexp(char *);
  71. static char      *getop(char *);
  72. static void       pack(char *);
  73.  
  74. #ifdef TEST
  75.  
  76. void main(int argc, char *argv[])
  77. {
  78.       double val;
  79.  
  80.       printf("evaluate(%s) ", argv[1]);
  81.       printf("returned %d\n", evaluate(argv[1], &val));
  82.       printf("val = %f\n", val);
  83. }
  84.  
  85. #endif
  86.  
  87. /*
  88. **  Evaluate a mathematical expression
  89. */
  90.  
  91. int evaluate(char *line, double *val)
  92. {
  93.       double arg;
  94.       char *ptr = line, *str, *endptr;
  95.       int ercode;
  96.  
  97.       pack(line);
  98.  
  99.       while (*ptr)
  100.       {
  101.             switch (state)
  102.             {
  103.             case 0:
  104.                   if (NULL != (str = getexp(ptr)))
  105.                   {
  106.                         if ('(' == *str)
  107.                         {
  108.                               push_op(*str);
  109.                               ptr += strlen(str);
  110.                               break;
  111.                         }
  112.  
  113.                         if (0.0 == (arg = strtod(str, &endptr)) &&
  114.                               NULL == strchr(str, '0'))
  115.                         {
  116.                               return ERROR;
  117.                         }
  118.                         push_arg(arg);
  119.                         ptr += strlen(str);
  120.                   }
  121.                   else  return ERROR;
  122.  
  123.                   state = 1;
  124.                   break;
  125.  
  126.             case 1:
  127.                   if (NULL == (str = getop(ptr)))
  128.                         return ERROR;
  129.  
  130.                   if (strchr(delims, *str))
  131.                   {
  132.                         if (')' == *str)
  133.                         {
  134.                               if (SUCCESS > (ercode = do_paren()))
  135.                                     return ercode;
  136.                         }
  137.                         else
  138.                         {
  139.                               push_op(*str);
  140.                               state = 0;
  141.                         }
  142.  
  143.                         ptr += strlen(str);
  144.                   }
  145.                   else  return ERROR;
  146.  
  147.                   break;
  148.             }
  149.       }
  150.  
  151.       while (1 < arg_sptr)
  152.       {
  153.             if (SUCCESS > (ercode = do_op()))
  154.                   return ercode;
  155.       }
  156.       if (!op_sptr)
  157.